package com.liveinstars.api.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import feign.Request;
import feign.Retryer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.Arrays;
import java.util.List;

/**
 * Created by guoyanjiang on 2018-11-29.
 */
@Configuration
public class FeignConfig implements WebMvcConfigurer {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Bean
    Request.Options feignOptions() {
        return new Request.Options(20 * 1000, 20 * 1000);
    }

    @Bean
    Retryer feignRetryer() {
        return Retryer.NEVER_RETRY;
    }

    @Bean("fastJsonHttpMessageConverter")
    public HttpMessageConverter initFastJsonHttpMessageConverter(){
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        //自定义配置... 同时把FastJson配下全局
        FastJsonConfig config = new FastJsonConfig();
        SerializeConfig serializeConfig = SerializeConfig.getGlobalInstance();
        serializeConfig.propertyNamingStrategy = com.alibaba.fastjson.PropertyNamingStrategy.SnakeCase;
        JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.WRITE_MAP_NULL_FEATURES;

        config.setSerializeConfig(serializeConfig);
        converter.setFastJsonConfig(config);

        converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON_UTF8));
        return converter;
    }

    @Autowired
    @Qualifier("fastJsonHttpMessageConverter")
    HttpMessageConverter fastJsonHttpMessageConverter;

    /**
     * 配置SpringMVC的消息转换器<br/>
     * 在Spring Cloud环境下，Feign的Encoder只会用来编码没有添加注解的参数。如果你自定义了Encoder, 那么只有在编码obj参数时才会调用你的Encoder。<br/>
     * 对于Decoder, 默认会委托给SpringMVC中的XHttpMessageConverter类进行解码。<br/>
     * 只有当状态码不在200 ~ 300之间时ErrorDecoder才会被调用。ErrorDecoder的作用是可以根据HTTP响应信息返回一个异常，该异常可以在调用Feign接口的地方被捕获到。
     * @see <a href="https://github.com/alibaba/fastjson/wiki/%E5%9C%A8-Spring-%E4%B8%AD%E9%9B%86%E6%88%90-Fastjson">在Spring中集成Fastjson</a>
     * @param converters
     */
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {

        //诡异+1 若不实现这个方法，Decode时converters也会加入上面的fastJsonHttpMessageConverter实例，但json输出格式有问题
        //诡异+2 若在这个方法里，再给converters添加fastJsonHttpMessageConverter实例，Decode时会有两个实例引用（其实是同一个实例），但json输出格式仍有问题
        //诡异+3 将第一个（也就是自动注入的那个fastJsonHttpMessageConverter）删掉...Decode时仍会有一个它的实例，同时json输出格式正常了
        //诡异+4 但是...如果将第一个删掉，Encode时就没了，导致某些参数解析失败（尤其是POST+Bean+驼峰的字段）

        converters.remove(0); //所以这个不能删=。=，但json响应有问题，那就先删掉然后换个位置放

        //不清楚在哪还会自动将fastJsonHttpMessageConverter放converters里，这里根本没必要加...
        converters.add(5, fastJsonHttpMessageConverter);
//        converters.add(fastJsonHttpMessageConverter);
        logger.info("do some thing about extendMessageConverters in feign config, converters size {}", converters.size());
    }
}
